package toolkit

import (
	"fmt"
	"log"
	"strings"

	"github.com/playwright-community/playwright-go"
)

// PageToolkit 封装的网页操作工具
type PageToolkit struct {
	Browser         playwright.Browser
	Context         playwright.BrowserContext
	Page            playwright.Page
	isRecording     bool
	recordedActions []string
}

// NewBrowser 创建新的浏览器实例
func NewBrowser(headless bool) (*PageToolkit, error) {
	pw, err := playwright.Run()
	if err != nil {
		return nil, fmt.Errorf("无法启动 Playwright: %v", err)
	}

	browser, err := pw.Chromium.Launch(playwright.BrowserTypeLaunchOptions{
		ExecutablePath: playwright.String("C:\\Users\\srand\\AppData\\Local\\Chromium\\Application\\chrome.exe"),
		Headless:       playwright.Bool(headless),
	})
	if err != nil {
		return nil, fmt.Errorf("无法启动 Chromium 浏览器: %v", err)
	}

	context, err := browser.NewContext(playwright.BrowserNewContextOptions{
		AcceptDownloads: playwright.Bool(true),
	})
	if err != nil {
		return nil, fmt.Errorf("无法创建浏览器上下文: %v", err)
	}

	return &PageToolkit{
		Browser: browser,
		Context: context,
	}, nil
}

// NewPage 打开新的页面
func (p *PageToolkit) NewPage(url string) (*PageToolkit, error) {
	page, err := p.Context.NewPage()
	if err != nil {
		return nil, fmt.Errorf("无法创建新页面: %v", err)
	}

	// 导航到指定的 URL
	if _, err := page.Goto(url); err != nil {
		return nil, fmt.Errorf("无法跳转到指定 URL: %v", err)
	}

	p.Page = page
	return p, nil
}

// Close 关闭浏览器
func (p *PageToolkit) Close() error {
	if err := p.Browser.Close(); err != nil {
		return fmt.Errorf("无法关闭浏览器: %v", err)
	}
	return nil
}

// GetAttribute 获取元素的指定属性值
func (p *PageToolkit) GetAttribute(selector, attribute string) (string, error) {
	locator := p.Page.Locator(selector)
	if count, _ := locator.Count(); count == 0 {
		return "", fmt.Errorf("未找到选择器 %v 对应的元素", selector)
	}
	attr, err := locator.GetAttribute(attribute)
	if err != nil {
		return "", fmt.Errorf("无法获取选择器 %v 的属性 %v: %v", selector, attribute, err)
	}
	return attr, nil
}

// GetAllAttributes 获取所有匹配元素的指定属性值
func (p *PageToolkit) GetAllAttributes(selector, attribute string) ([]string, error) {
	locators := p.Page.Locator(selector)
	count, err := locators.Count()
	if err != nil || count == 0 {
		return nil, fmt.Errorf("未找到选择器 %v 对应的任何元素", selector)
	}
	var attributes []string
	for i := 0; i < count; i++ {
		attr, _ := locators.Nth(i).GetAttribute(attribute)
		if attr != "" {
			attributes = append(attributes, attr)
		}
	}
	return attributes, nil
}

// SetInputValue 设置输入框的值
func (p *PageToolkit) SetInputValue(selector, value string) error {
	locator := p.Page.Locator(selector)
	if count, _ := locator.Count(); count == 0 {
		return fmt.Errorf("未找到选择器 %v 对应的输入框", selector)
	}
	if err := locator.Fill(value); err != nil {
		return fmt.Errorf("无法填充输入框: %v", err)
	}
	return nil
}

// Click 点击指定元素
func (p *PageToolkit) Click(selector string) error {
	locator := p.Page.Locator(selector)
	if count, _ := locator.Count(); count == 0 {
		return fmt.Errorf("未找到选择器 %v 对应的元素", selector)
	}
	if err := locator.Click(); err != nil {
		return fmt.Errorf("无法点击元素: %v", err)
	}
	return nil
}

// Keyboard 执行键盘事件
func (p *PageToolkit) Keyboard(key string) error {
	err := p.Page.Keyboard().Press("Enter")
	if err != nil {
		return fmt.Errorf("无法按键 %v: %v", key, err)
	}
	return nil
}

func (p *PageToolkit) ClickForWait(selector string) error {
	if err := p.WaitForElement(selector); err != nil {
		log.Printf("等待页面加载异常：%v", err)
		return err
	}
	return p.Click(selector)
}

func (p *PageToolkit) GetCurrentPage() (playwright.Page, error) {
	// 获取当前 context 下的所有页面
	pages := p.Context.Pages()
	// 假设最后一个页面是当前活动页面
	if len(pages) > 0 {
		return pages[len(pages)-1], nil
	}

	return nil, fmt.Errorf("没有找到当前活动页面")
}

// Screenshot 截取屏幕截图
func (p *PageToolkit) Screenshot(path string) error {
	if _, err := p.Page.Screenshot(playwright.PageScreenshotOptions{
		Path: playwright.String(path),
	}); err != nil {
		return fmt.Errorf("无法截取屏幕截图: %v", err)
	}
	return nil
}

// DownloadFile 下载文件
func (p *PageToolkit) DownloadFile(selector, downloadPath string) error {
	locator := p.Page.Locator(selector)
	if count, _ := locator.Count(); count == 0 {
		return fmt.Errorf("未找到选择器 %v 对应的元素", selector)
	}
	url, _ := locator.GetAttribute("href")
	if url != "" {
		fmt.Printf("文件下载地址: %s\n", url)
		// 此处可以扩展为实际文件下载逻辑
	}
	return nil
}

// WaitForElement 等待元素出现
func (p *PageToolkit) WaitForElement(selector string) error {
	if err := p.Page.Locator(selector).WaitFor(); err != nil {
		return fmt.Errorf("等待选择器 %v 对应的元素时发生错误: %v", selector, err)
	}
	return nil
}

// ScrollToBottom 滚动到页面底部
func (p *PageToolkit) ScrollToBottom() error {
	if _, err := p.Page.Evaluate(`window.scrollTo(0, document.body.scrollHeight)`); err != nil {
		return fmt.Errorf("无法滚动到页面底部: %v", err)
	}
	return nil
}

// GetTextContent 获取指定选择器的文本内容
func (p *PageToolkit) GetTextContent(selector string) (string, error) {
	locator := p.Page.Locator(selector)
	if count, _ := locator.Count(); count == 0 {
		return "", fmt.Errorf("未找到选择器 %v 对应的元素", selector)
	}
	text, err := locator.TextContent()
	if err != nil {
		return "", fmt.Errorf("无法获取选择器 %v 的文本内容: %v", selector, err)
	}
	return text, nil
}

// GetAllTextContent 获取所有匹配元素的文本内容
func (p *PageToolkit) GetAllTextContent(selector string) ([]string, error) {
	locators := p.Page.Locator(selector)
	count, err := locators.Count()
	if err != nil || count == 0 {
		return nil, fmt.Errorf("未找到选择器 %v 对应的任何元素", selector)
	}
	var texts []string
	for i := 0; i < count; i++ {
		text, _ := locators.Nth(i).TextContent()
		if text != "" {
			texts = append(texts, text)
		}
	}
	return texts, nil
}

// GetImageURLs 获取所有图片的 URL
func (p *PageToolkit) GetImageURLs(selector string) ([]string, error) {
	locators := p.Page.Locator(selector)
	count, err := locators.Count()
	if err != nil || count == 0 {
		return nil, fmt.Errorf("未找到选择器 %v 对应的任何图片", selector)
	}
	var urls []string
	for i := 0; i < count; i++ {
		url, _ := locators.Nth(i).GetAttribute("src")
		if url != "" {
			urls = append(urls, url)
		}
	}
	return urls, nil
}

// GetLinks 获取所有链接的 URL
func (p *PageToolkit) GetLinks(selector string) ([]string, error) {
	locators := p.Page.Locator(selector)
	count, err := locators.Count()
	if err != nil || count == 0 {
		return nil, fmt.Errorf("未找到选择器 %v 对应的任何链接", selector)
	}
	var links []string
	for i := 0; i < count; i++ {
		href, _ := locators.Nth(i).GetAttribute("href")
		if href != "" {
			links = append(links, href)
		}
	}
	return links, nil
}

// GetVideoSources 获取所有视频的 source URL
func (p *PageToolkit) GetVideoSources(selector string) ([]string, error) {
	locators := p.Page.Locator(selector)
	count, err := locators.Count()
	if err != nil || count == 0 {
		return nil, fmt.Errorf("未找到选择器 %v 对应的任何视频", selector)
	}
	var sources []string
	for i := 0; i < count; i++ {
		src, _ := locators.Nth(i).GetAttribute("src")
		if src != "" {
			sources = append(sources, src)
		}
	}
	return sources, nil
}

// FormField 表单字段结构，包含英文字段名称和中文名称
type FormField struct {
	EnglishName string // 英文字段名称 (name属性)
	ChineseName string // 中文名称 (label文本)
	Value       string // 字段值
	IsRequired  bool   // 是否必填
}

// GetFormValues 获取表单中的所有字段及其值，包含中文名称和英文字段名称
func (p *PageToolkit) GetFormValues(selector string) (map[string]FormField, error) {
	form := p.Page.Locator(selector)
	if count, _ := form.Count(); count == 0 {
		return nil, fmt.Errorf("未找到选择器 %v 对应的表单", selector)
	}

	fields := form.Locator("input, select, textarea")
	count, err := fields.Count()
	if err != nil || count == 0 {
		return nil, fmt.Errorf("未找到表单中的任何字段")
	}

	values := make(map[string]FormField)
	for i := 0; i < count; i++ {
		field := fields.Nth(i)
		englishName, _ := field.GetAttribute("name")
		value, _ := field.InputValue()

		// 获取对应的中文名称
		labelLocator := p.Page.Locator(fmt.Sprintf("label[for='%s']", englishName))
		chineseName, _ := labelLocator.TextContent()

		// 如果找不到中文名称，则使用英文字段名称
		if chineseName == "" {
			chineseName = englishName
		}

		if englishName != "" {
			values[englishName] = FormField{
				EnglishName: englishName,
				ChineseName: chineseName,
				Value:       value,
			}
		}
	}
	return values, nil
}

// ValidateForm 验证表单，检查必填字段是否填写
func (p *PageToolkit) ValidateForm(formSelector string) error {
	formFields, err := p.GetFormValues(formSelector)
	if err != nil {
		return fmt.Errorf("获取表单值时出错: %v", err)
	}

	for _, field := range formFields {
		// 如果字段是必填且没有值，则返回错误
		if field.IsRequired && strings.TrimSpace(field.Value) == "" {
			return fmt.Errorf("字段 %s (%s) 为必填项，请填写", field.EnglishName, field.ChineseName)
		}
	}

	return nil
}

// GetTableContent 获取表格内容
func (p *PageToolkit) GetTableContent(selector string) ([][]string, error) {
	table := p.Page.Locator(selector)
	if count, _ := table.Count(); count == 0 {
		return nil, fmt.Errorf("未找到选择器 %v 对应的表格", selector)
	}

	rows := table.Locator("tr")
	rowCount, err := rows.Count()
	if err != nil || rowCount == 0 {
		return nil, fmt.Errorf("未找到表格中的任何行")
	}

	var tableContent [][]string
	for i := 0; i < rowCount; i++ {
		row := rows.Nth(i)
		cells := row.Locator("th, td")
		cellCount, _ := cells.Count()
		var rowContent []string
		for j := 0; j < cellCount; j++ {
			text, _ := cells.Nth(j).TextContent()
			rowContent = append(rowContent, text)
		}
		tableContent = append(tableContent, rowContent)
	}
	return tableContent, nil
}
